; crt0.asm - system entry and basic architecture initialization
; service.ld references crt0.o:start as the service entry point
;
;  Copyright 2006 Corey Tabaka
;
;  Licensed under the Apache License, Version 2.0 (the "License");
;  you may not use this file except in compliance with the License.
;  You may obtain a copy of the License at
;
;      http://www.apache.org/licenses/LICENSE-2.0
;
;  Unless required by applicable law or agreed to in writing, software
;  distributed under the License is distributed on an "AS IS" BASIS,
;  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
;  See the License for the specific language governing permissions and
;  limitations under the License.
;
section .text

[extern _main]

[extern start_ctors]
[extern end_ctors]
[extern start_dtors]
[extern end_dtors]

[extern bss]
[extern bss_end]

[extern _cprintf]
[extern _place]

[global start]
[global __exit]

;%define DEBUG 1


bits 32
start:	
	; C environment initialization
	
	; zero the bss section
;	mov edi,bss				; starting address of the bss
;	mov ecx,bss_end			; find the length of the bss in bytes
;	sub ecx,edi
;	shr ecx,2				; convert to dwords, since the bss is page aligned anyway
;.loop2:
;	mov dword [edi],0
;	add edi,4
;	loop .loop2

%ifdef DEBUG
	sub esp,32				; make space for params on the stack
	mov dword [esp + 4],8
	mov dword [esp],0
	call _place
	
	mov dword [esp + 16],end_dtors
	mov dword [esp + 12],start_dtors
	mov dword [esp + 8],end_ctors
	mov dword [esp + 4],start_ctors
	mov dword [esp],format_string
	call _cprintf
	
	add esp,32				; move the stack frame back
%endif
	
	; call constructors
	call do_ctors
	
	; call the primary module
	call _main
	ret

__exit:
	
	; call destructors
	call do_dtors
	ret

.stop:						; just sit around waiting to die
	pause
	jmp .stop				; so jump back to halt to conserve power

; call global constructors
do_ctors:
	mov edi,start_ctors		; load start of the constructor list
	cmp edi,end_ctors		; see if the list is empty
	je .done
.loop:
	call dword [edi]
	add edi,4				; move to the next entry
	cmp edi,end_ctors
	jne .loop
.done:
	ret

; call global destructors
do_dtors:
	mov edi,start_dtors		; load start of the destructor list
	cmp edi,end_dtors		; see if the list is empty
	je .done
.loop:
	call dword [edi]
	add edi,4				; move to the next entry
	cmp edi,end_dtors
	jne .loop
.done:
	ret
